package com.ciaojian.worker.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ciaojian.core.constant.RedisConstant;
import com.ciaojian.core.enums.business.OrderOrderTypeEnum;
import com.ciaojian.core.enums.business.OrderStatusEnum;
import com.ciaojian.core.enums.business.WorkerWorkerStatusEnum;
import com.ciaojian.core.mapper.*;
import com.ciaojian.core.model.*;
import com.ciaojian.core.model.Order;
import com.ciaojian.core.model.dto.LoginDTO;
import com.ciaojian.core.model.vo.*;
import com.ciaojian.core.service.WorkerService;
import com.ciaojian.core.util.*;
import com.ciaojian.miniapp.api.WxMiniAppApi;
import com.ciaojian.miniapp.model.request.submessage.BaseTemplate;
import com.ciaojian.miniapp.model.request.submessage.TakeChangeMessage;
import com.ciaojian.miniapp.model.request.submessage.TakeNumMessage;
import com.ciaojian.miniapp.model.request.submessage.TemplateIdEnum;
import com.ciaojian.miniapp.model.response.SubMessageSendResponse;
import com.ciaojian.worker.model.query.WorkerOrderQuery;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Atlakyn
 */
@Service
public class WorkerServiceImpl extends WorkerService<WorkerMapper, Worker> implements IService<Worker> {
    @Resource
    private OrderServiceImpl orderService;
    @Resource
    private RedisTemplate<String, Integer> redisTemplate;
    @Resource
    private OrderCouponRecordServiceImpl orderCouponRecordService;
    @Resource
    private UserTimesCardServiceImpl userTimesCardService;
    @Resource
    private UserMemberServiceImpl<UserMemberMapper, UserMember> userMemberService;
    @Resource
    private UserTagServiceImpl userTagService;
    @Resource
    private OrderCommentServiceImpl orderCommentService;
    @Resource
    private OrderCommissionServiceImpl orderCommissionService;
    @Resource
    private SchedulingMapper schedulingMapper;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private CouponCodeMapper couponCodeMapper;

    /**
     * 发型师轻餐
     *
     * @param worker 发型师
     * @return 修改成分返回TRUE
     */
    public Boolean afternoonTea(Worker worker) {
        // 限发型师 30 分钟内吃完,往后推 15 分钟结束干饭时间(毫秒),用于定时器查找
        redisTemplate.opsForZSet().add(RedisConstant.WORKER_AFTERNOON_TEA, worker.getId(), DateUtil.current() + 15 * 60 * 1000);
        worker.setWorkerStatus(WorkerWorkerStatusEnum.AFTERNOON_TEA);
        // 用于给前端展示的时间
        RedisUtil.setKeyTime(RedisConstant.WORKER_AFTERNOON_TEA + worker.getId(), 15 * 60 * 1000, DateUtil.now());
        return worker.updateById();
    }

    /**
     * 发型师干饭
     *
     * @param worker 发型师
     * @return 干饭结果
     */
    public Boolean dinner(Worker worker) {
        // 限发型师 30 分钟内干完,往后推 30 分钟结束干饭时间(毫秒),用于定时器查找
        redisTemplate.opsForZSet().add(RedisConstant.WORKER_DINNER, worker.getId(), DateUtil.current() + 15 * 60 * 1000);
        worker.setWorkerStatus(WorkerWorkerStatusEnum.EATING);
        // 用于给前端展示的时间
        RedisUtil.setKeyTime(RedisConstant.WORKER_DINNER + worker.getId(), 15 * 60 * 1000, DateUtil.now());
        return worker.updateById();
    }

    public Result cancelOrder(Integer id) {
        if (StringUtil.isHasEmpty(id)) {
            return Result.error("订单ID不能为空");
        }
        Integer orderStatus = baseMapper.getOrderStatus(id);
        if (orderStatus != 0) {
            return Result.error("非排队订单无法取消");
        }
        // 取消用户订单
        baseMapper.cancelOrder(id);
        return Result.ok();
    }

    public Result findWorkerPhoto(String userId) {
        if (StringUtil.isHasEmpty(userId)) {
            return Result.error("发型师ID不能为空");
        }
        List<WorkerPhoto> workerPhoto = baseMapper.findWorkerPhoto(userId);
        for (WorkerPhoto data : workerPhoto) {
            data.setUrls(data.getUrl().split(","));
            data.setUrl(null);
        }
        return Result.ok(workerPhoto);
    }

    public Result delWorkerPhoto(String ids) {
        if (StringUtil.isHasEmpty(ids)) {
            return Result.error("请选择你要删除的作品");
        }
        for (String id : ids.split(",")) {
            baseMapper.delWorkerPhoto(id);
        }
        return Result.ok();
    }

    public Result findDRosterList(String storeId) {
        List<Roster> dRosterList = baseMapper.findDRosterList(storeId);
        return Result.ok(dRosterList);
    }

    public Result saveDCheckAskfor(DCheckAskfor data) throws Exception {
        Integer compareDate = baseMapper.startEndTime(data.getStart(), data.getEnd());
        if (compareDate > 0) {
            return Result.error("开始时间不能大于结束时间");
        }
        if (data.getStart().equals(data.getEnd())) {
            return Result.error("开始时间不能与结束时间一样");
        }
        Integer startTime = baseMapper.greaterDay(data.getStart());
        Integer endTime = baseMapper.greaterDay(data.getEnd());
        if (startTime < 1 || endTime < 1) {
            return Result.error("请假时间必须是今天起");
        }
        String timeNum = baseMapper.finalTime(data.getEnd(), data.getStart());
        if (Integer.parseInt(timeNum) < 14400) {
            return Result.error("请假时间段不能小于4小时");
        }
        // 开始时间
        Integer startafternoon = baseMapper.getAfternoon(data.getStart());
        // 结束时间
        Integer endafternoon = baseMapper.getAfternoon(data.getEnd());
        if (startafternoon == 1) {
            data.setStartAfternoon("下午");
        } else {
            data.setStartAfternoon("上午");
        }
        if (endafternoon == 1) {
            data.setEndAfternoon("下午");
        } else {
            data.setEndAfternoon("上午");
        }

        // 获取请假2个时间之间的天数
        BigDecimal leaveDay = getLeaveDay(data.getStart(), data.getEnd());
        data.setDay(leaveDay + "");
        baseMapper.saveDCheckAskfor(data);
        return Result.ok(null);
    }

    private static BigDecimal getLeaveDay(String start, String end) throws Exception {
        long startTime = Long.parseLong(StringUtil.dateToStamp(start)) / 1000;
        long endTime = Long.parseLong(StringUtil.dateToStamp(end)) / 1000;
        double div = BigDecimalUtil.div(((endTime - startTime) / 3600), 24);
        BigDecimal bd = new BigDecimal(div);
        bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);
        return bd;
    }


    public Result saveDWorkerPhoto(WorkerPhoto data) {
        if (StringUtil.isHasEmpty(data.getTitle())) {
            return Result.error("作品标题不能为空");
        }
        if (StringUtil.isHasEmpty(data.getDesc())) {
            return Result.error("作品描述不能为空");
        }
        if (StringUtil.isHasEmpty(data.getUserId())) {
            return Result.error("作品作者不能为空");
        }
        String[] urls = data.getUrls();
        if (urls.length < 1) {
            return Result.error("作品图片不能为空");
        }
        if (urls.length > 6) {
            return Result.error("最多一次性上传6张图片");
        }
        Integer workerPhotoCount = baseMapper.getWorkerPhotoCount(data.getUserId());
        if (workerPhotoCount >= 6) {
            return Result.error("一个发型师最多上传6个作品");
        }
        StringBuilder imgUrl = new StringBuilder();
        for (String url : urls) {
            imgUrl.append(url).append(",");
            baseMapper.delDImageUpload(url);
        }
        imgUrl = new StringBuilder(imgUrl.substring(0, imgUrl.length() - 1));
        data.setUrl(imgUrl.toString());
        baseMapper.saveDWorkerPhoto(data);
        return Result.ok();
    }

    public Result thisMonthCount(String id) {
        Integer integer = baseMapper.thisMonthCount(id);
        return Result.ok(integer);
    }

    public Result getAttendanceSummary(String date, String id) {
        baseMapper.setSqlMode();
        // 获取某个月有多少天
        Integer moneyDay = baseMapper.getMoneyDay(date + "-01");
        DAttendance data = baseMapper.getAttendanceSummary(date, id);
        if (data != null) {
            data.setRestDays(moneyDay - data.getAttendanceDays());
        }
        if (data.getAttendanceDays() == 0) {
            return Result.ok(null);
        }
        return Result.ok(data);
    }

    public Result saveDCheckUser(CheckUser data) {
        Integer checkUserDk = baseMapper.isCheckUserDk(data.getUserId(), data.getType());
        if (checkUserDk > 0) {
            baseMapper.delCheckUserDk(data.getUserId(), data.getType());
        }
        data.setDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        data.setTime(new SimpleDateFormat("HH:mm:ss").format(new Date()));
        baseMapper.saveDCheckUser(data);
        // 修改为上班的状态
        if ("上班打开".equals(data.getType())) {
            baseMapper.edidWorkerStatus("0", data.getUserId());
        } else if ("下班打卡".equals(data.getType())) {
            baseMapper.edidWorkerStatus("2", data.getUserId());
        }
        return Result.ok();
    }

    public Result updateOrderStatus(Order data) {
        if (data.getStatus().equals(OrderStatusEnum.servicing)) {
            baseMapper.updateServiceTime(data.getId());
        }
        // 顾客当前订单之前已完成和已支付的订单数
        Integer count = orderService.countNumberOfComplete(data);
        if (data.getStatus().equals(OrderStatusEnum.wait_pay)) {
            data.setStatus(OrderStatusEnum.paid)
                    .setPayType("美团支付")
                    .setPayTime(new Date());
            orderService.setCustomerType(data);
            data.updateById();
        } else {
            orderService.setCustomerType(data);
            baseMapper.updateOrderStatus(data.getStatus(), data.getId());
        }
        Worker worker = new Worker().selectById(data.getWorkerId());
        new Oplog()
                .setTelphone(worker.getTelphone())
                .setAccount(worker.getName())
                .setWorkerId(worker.getId())
                .setModular("发型师修改订单状态")
                .setContent("发型师修改订单状态为" + data.getStatus().getValue())
                .insert();
        return Result.ok();
    }

    public Result meituanOrder(Integer id, String payTotal, String youzanCode) {
        boolean flagMoney = StringUtil.checkMoney(payTotal);
        if (!flagMoney) {
            return Result.error("美团金额错误");
        }
        Integer orderStatus = baseMapper.getOrderStatus(id);
        if (orderStatus < 2) {
            return Result.error("服务未完成无法修改为美团订单");
        }
        baseMapper.meituanOrder(id, payTotal, youzanCode);
        return Result.ok();
    }

    public Result getDHeaderCount(String id) {
        DHeaderCount HeaderCount = baseMapper.getDHeaderCount(id);
        return Result.ok(HeaderCount);
    }


    /**
     * 查询上下班时间
     */
    public Result getStartEndWorkTime(DCheckUserTime data) {
        Worker workerData = baseMapper.getWorkerStatus(data.getId());
        DCheckUserTimeVo startEndWorkTime = baseMapper.getStartEndWorkTime(data);
        List<CheckUser> typeDate = baseMapper.getTypeDate(data.getId() + "");
        if (startEndWorkTime != null) {
            startEndWorkTime.setDCheckUserList(typeDate);
            startEndWorkTime.setId(workerData.getId());
            startEndWorkTime.setPhone(workerData.getTelphone());
            startEndWorkTime.setName(workerData.getName());
            Integer workerRosterId = schedulingMapper.getWorkerRosterId(data.getId());
            startEndWorkTime.setRosterId(workerRosterId);
        }
        if (workerData != null && startEndWorkTime != null) {
            startEndWorkTime.setWorkerStatus(workerData.getWorkerStatus().getValue());
            String minute30 = baseMapper.addMinute30(workerData.getEatTime() + "");
            if (minute30 != null) {
                String timeNum = baseMapper.finalTime(minute30, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                // 如果主动修改为上班状态，就餐时间之间清除
                if (workerData.getWorkerStatus().getValue() == 0) {
                    startEndWorkTime.setTimeNum(null);
                } else if (workerData.getWorkerStatus().getValue() == 1) {
                    if (Integer.parseInt(timeNum) <= 0) {
                        startEndWorkTime.setTimeNum(0);
                    } else {
                        startEndWorkTime.setTimeNum(Integer.parseInt(timeNum));
                    }
                }
            }
        }
        return Result.ok(startEndWorkTime);
    }


    public Result getWorkerData(Integer storeId, Date startDate, Date endDate, Integer pageNo, Integer pageSize) {
        Page<WorkerDataVO> dWorkerDataVoPage = baseMapper.getWorkerData(new Page<>(pageNo, pageSize), startDate, endDate, storeId, pageNo);

        return Result.ok(dWorkerDataVoPage);
    }

    public PersonaDataVO findPersonalData(Integer workerId, Date startDate, Date endDate) {
        return baseMapper.getPersonalData(workerId, startDate, endDate);
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> findPersonalDataV2(Integer storeId,Integer workerId, Date beginDate, Date endDate) {
        OrderMapper orderMapper = orderService.getBaseMapper();
        // 会员订单(新/老)
        Map<String, Integer> newAndOldMemberNum = orderMapper.countNewAndOldMember(storeId, workerId, beginDate, endDate);
        if (ObjectUtil.isNull(newAndOldMemberNum)){
            newAndOldMemberNum = new HashMap<>();
            newAndOldMemberNum.put("newCustomer",0);
            newAndOldMemberNum.put("oldCustomer",0);
        }

        // 剪发订单量
        Integer cutHairNum = orderService.countCompleted(OrderOrderTypeEnum.NORMAL, workerId,storeId, beginDate, endDate);

        // 差评数
        Integer badCommentNum = orderCommentService.countComment(storeId, workerId, 1, beginDate, endDate);
        // 新人优惠订单
        Integer newCustomerNum = orderMapper.countNewCustomerNum(storeId, workerId, beginDate, endDate);
        // 抖音订单数
        Integer douyinNum = orderService.countCompleted(OrderOrderTypeEnum.DOUYIN_WRITE_OFF, workerId,storeId, beginDate, endDate);
        // 抖音转会员
        Integer douyinTurnMemberNum = orderMapper.countDouyinChengeMember(workerId, storeId, beginDate, endDate);
        // 本月累计业绩
        Integer amount = orderCommissionService.getBaseMapper().sumAmount(workerId, new Integer[]{0, 3}, beginDate, endDate);

        BigDecimal workerAmount = new BigDecimal(0);
        if (storeId!=null) {
            // 本月实际业绩
            workerAmount = orderMapper.sumAmount(storeId, workerId, beginDate, endDate);
            if (workerAmount!=null) {
                workerAmount.setScale(2);
            }else {
                workerAmount = new BigDecimal(0);
            }
        }

        WorkerInfoVO workerInfo = this.baseMapper.getWorkerInfoById(workerId);
        Map<String, Object> map = new HashMap<>(7);
        map.putAll(newAndOldMemberNum);
        map.put("workerId", workerId);
        map.put("cutHairNum", cutHairNum);
        map.put("badCommentNum", badCommentNum);
        map.put("newCustomerNum", newCustomerNum);
        map.put("douyinNum", douyinNum);
        map.put("douyinTurnMemberNum", douyinTurnMemberNum);
        map.put("amount", amount);
        map.put("workerInfo", workerInfo);
        map.put("workerAmount", workerAmount);
        return map;
    }

    /**
     * 登录
     *
     * @param phone  手机号
     * @param openId 微信 openId
     * @return 发型师信息
     */
    public LoginDTO login(String phone, String openId) {
        LoginDTO loginDTO = this.getBaseMapper().getByPhone(phone);
        Assert.notNull(loginDTO, "账号不存在");
        loginDTO.setToken(TokenUtil.makeToken(openId));
        loginDTO.setOpenId(openId);
        this.getBaseMapper().updateOpenId(phone, openId);
        return loginDTO;
    }


    public HashMap<String, Object> findWorkerOrder(WorkerOrderQuery data) {
        int pageNum = data.getPageNum();
        Page<Map<String, Object>> page = this.baseMapper.getWorkerOrder(new Page<>(data.getPageNum(), data.getPageSize()), BeanUtil.beanToMap(data));

        if (page.getRecords().size() > 0) {
            page.getRecords().forEach(order -> {
                Integer userId = (Integer) order.get("userId");
                List<UserTimesCard> timesCards = userTimesCardService.getCardInfo(
                        userId,
                        (Integer) order.get("storeId"),
                        (String) order.get("type"));
                order.put("timesCards", timesCards);
                // 用券记录
                order.put("orderCouponRecords", orderCouponRecordService.lambdaQuery()
                        .eq(OrderCouponRecord::getOrderId, order.get("id")).list());
                order.put("memberDetailRecords", orderService.lambdaQuery()
                        .eq(Order::getUserId, userId)
                        .eq(Order::getOrderType, OrderOrderTypeEnum.MEMBER_DETAIL)
                        .in(Order::getStatus, OrderStatusEnum.complete, OrderStatusEnum.paid)
                        .orderByDesc(Order::getAddTime)
                        .last("limit 3").list());
                // 是否有标签
//                order.put("tag", userTagService.getBaseMapper().countByUserId(userId) > 0);

                LambdaQueryWrapper<HaircutService> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(HaircutService::getTitle, MapUtil.getStr(order, "type"));
                HaircutService haircutService = new HaircutService().selectOne(queryWrapper);
                // 因为用的服务字符串来联表,所以可能因为更改了服务名造成了查找不到而引起空指针异常
                Assert.notNull(haircutService, "服务:" + MapUtil.getStr(order, "type") + "不存在");
                order.put("serviceType", haircutService.getType().getDescription());

                Integer memBerCount = baseMapper.getMemBerCount(MapUtil.getStr(order, "userId"));
                if (memBerCount > 0) {
                    order.put("isMember", 1);
                } else {
                    order.put("isMember", 0);
                }

                order.put("userMember", userMemberService.getBaseMapper().getByUserId(userId));

                //剩余套餐券券
                Integer count1 = couponCodeMapper.selectMemberCount(userId);
                order.put("couponMemberNum", count1);

                CheckUser dCheckUser = new CheckUser();
                dCheckUser.setUserId(MapUtil.getInt(order, "userId"));
                dCheckUser.setId(MapUtil.getLong(order, "workerId"));
                Integer userOrderCount = baseMapper.getUserOrderCount(dCheckUser);
                order.put("orderCount", userOrderCount);
                // 有倒计时
                if (MapUtil.getInt(order, "status") == 1 && MapUtil.getDate(order, "serviceTime") != null) {
                    String minute10 = baseMapper.addMinute10(MapUtil.getStr(order, "serviceTime"));
                    String timeNum = baseMapper.finalTime(minute10, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    order.put("serviceTime", 1);
                }
                // 显示订单数
                QueryWrapper<Order> countWrapper = new QueryWrapper<>();
                countWrapper.eq("user_id", MapUtil.getInt(order, "userId"))
                        .in("status", 3, 5);
                Integer count = new Order().selectCount(countWrapper);
                order.put("count", count);
            });
            HashMap<String, Object> map = new HashMap<>(6);
            map.put("msg", "成功");
            map.put("code", 200);
            map.put("data", page.getRecords());
            map.put("pageNum", pageNum);
            map.put("pageSize", data.getPageSize());
            map.put("total", page.getTotal());
            return map;
        } else {
            HashMap<String, Object> map = new HashMap<>(3);
            map.put("msg", "成功");
            map.put("code", 200);
            map.put("data", page.getRecords());
            return map;
        }
    }


    @Transactional
    public Result orderSkipVo(OrderSkipVo orderSkipVo){
//        List<Order> orders = orderMapper.selectOrderNext(orderSkipVo.getWorkerId());
//        if (orders.size()!=2){
//            return Result.ok("无下位客户");
//        }
//        Order order = orders.get(0);
//        Order order1 = orders.get(1);
        if (ObjectUtil.isNull(orderSkipVo.getOriOrderId())||ObjectUtil.isNull(orderSkipVo.getTarOrderId())){
            return Result.ok("无下一位客户");
        }


        Order order = new Order().selectById(orderSkipVo.getOriOrderId());
        Order order1 = new Order().selectById(orderSkipVo.getTarOrderId());
        if (ObjectUtil.isNull(order)||ObjectUtil.isNull(order1)){
            return Result.ok("无下一位客户");
        }

        Date orderaboutRankTime = order.getAboutRankTime();
        Date order1aboutRankTime = order1.getAboutRankTime();

        order.setAboutRankTime(order1aboutRankTime);
        order1.setAboutRankTime(orderaboutRankTime);

        order.updateById();
        order1.updateById();

        Integer userId = order.getUserId();
        User user = new User().selectById(userId);

        BaseTemplate baseTemplate = BaseTemplate.builder(TemplateIdEnum.TAKE_CHANGE_MESSAGE)
                .touser(user.getOpenid())
                .data(TakeChangeMessage.builder()
                        .character_string1(order.getRankNo())
                        .thing2(order.getStoreName())
                        .thing3("您的排队已顺延一位，请尽快到店进行服务")
                        .build()
                );
        try {
            SubMessageSendResponse response = WxMiniAppApi.subscribeMessageSend(baseTemplate);
            if (response.getErrcode() == 0) {
            } else {
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            LogUtil.writeErrorLog(e.getMessage());
        }

        return Result.ok();
    }
}
